﻿(function ()
{

    if (!String.prototype.trim) {
        String.prototype.trim = function (str)
        {
            return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
        }
    }
    var dom = {
        quote: function (str)
        {
            str = str.replace(/[\x00-\x1f\\]/g, function (chr)
            {
                var special = metaObject[chr];
                return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)
            });
            return '"' + str.replace(/"/g, '\\"') + '"';
        }
    },
                metaObject = {
                    '\b': '\\b',
                    '\t': '\\t',
                    '\n': '\\n',
                    '\f': '\\f',
                    '\r': '\\r',
                    '\\': '\\\\'
                },
                startOfHTML = "\t__views.push(",
                endOfHTML = ");\n";
    (function ()
    {
        //http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
        var s = ["XMLHttpRequest",
                        "ActiveXObject('Msxml2.XMLHTTP.6.0')",
                        "ActiveXObject('Msxml2.XMLHTTP.3.0')",
                        "ActiveXObject('Msxml2.XMLHTTP')",
                        "ActiveXObject('Microsoft.XMLHTTP')"];
        if (eval("''+/*@cc_on" + " @_jscript_version@*/-0") * 1 === 5.7 && location.protocol === "file:") {
            s.shift();
        }
        for (var i = 0, el; el = s[i++]; ) {
            try {
                if (eval("new " + el)) {
                    dom.xhr = new Function("return new " + el)
                    break;
                }
            } catch (e) { }
        }
    })();

    dom.partial = function (url)
    {
        var xhr = dom.xhr();
        xhr.open("GET", url, false);
        xhr.setRequestHeader("If-Modified-Since", "0");
        xhr.send(null);
        return xhr.responseText || ""
    }

    dom.ejs = function (obj)
    {
        if (!arguments[1]) {
            obj.left = obj.left || "%>";
            obj.right = obj.right || "<%";
            obj.rLeft = new RegExp("\\s*" + obj.left + "\\s*");
            obj.rRight = new RegExp("\\s*" + obj.right + "\\s*");
        }
        var buff = ["var __views = [];\n"],
                    self = arguments.callee,
                    key = obj.selector || obj.url, str;
        if (obj.selector) {
            var el = document.getElementById(key);
            if (!el) throw "找不到目标元素";
            str = el.text;
        } else {
            str = dom.partial(key);
            if (!str) throw "目标文件不存在";
        }
        if (!self[key]) {//缓存模板函数
            var arr = str.trim().split(obj.rLeft), temp = [], segment, els, url, i = 0, n = arr.length;
            while (i < n) {
                segment = arr[i++];
                els = segment.split(obj.rRight);
                if (segment.indexOf(obj.right) !== -1) {//这里不使用els.length === 2是为了避开IE的split bug
                    switch (els[0].charAt(0)) {
                        case "#": //处理注释
                            break;
                        case "=": //处理后台返回的变量（输出到页面的);
                            temp.push(startOfHTML, els[0].substring(1), endOfHTML)
                            break;
                        case ":": //处理局部模板
                            delete obj.selector;
                            url = obj.url = els[0].substring(1).trim();
                            //缓存构筑函数的数组
                            self[url] = self[url] || self(obj, true);
                            temp = temp.concat(self[url]);
                            break;
                        default:
                            temp.push(els[0], "\n");
                    };
                    els[1] && temp.push(startOfHTML, dom.quote.call(null, els[1]), endOfHTML);
                } else {
                    temp.push(startOfHTML, dom.quote.call(null, els[0]), endOfHTML);
                }
            }
            if (arguments[1]) {
                return (self[key] = temp);
            } else {
                buff = buff.concat(temp);
                self[key] = new Function("json", "with(json){" + buff.join("") + '\t};return __views.join("");');
            }
        }
        return self[key](obj.json || {});
    };
    window.dom = dom;
})();